package com.frank.loadinglibrary.special.catload;

import com.frank.loadinglibrary.ResourceTable;
import com.frank.loadinglibrary.common.BaseLoadingComponent;
import com.frank.loadinglibrary.utils.Indicator;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorGroup;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.PixelMapHolder;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
import ohos.global.resource.NotExistException;
import ohos.global.resource.Resource;
import ohos.global.resource.WrongTypeException;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;

import java.io.IOException;
import java.util.ArrayList;

public class CatLoadingComponent extends BaseLoadingComponent implements Component.DrawTask {


    private PixelMapHolder mCatHold;
    private PixelMapHolder mMouseHold;
    private PixelMapHolder mEyeHold;
    float catWidth, catHeight;
    float mouseWidth, mouseHeight;
    private Paint mPaint;
    private Paint mEyesRectPaint;
    private Paint mEyesPaint;
    private Paint textPaint;
    private float mouseRorate = 0;
    private Indicator indicator;
    private Color mEyesRectColor = new Color(Color.getIntColor("#d0ced1"));
    private String text;
    private int textLength = 0;
    private float singleDuration;
    private float progress;

    public CatLoadingComponent(Context context) {
        this(context, null);
    }

    public CatLoadingComponent(Context context, AttrSet attrSet) {
        this(context, attrSet, "");
    }

    public CatLoadingComponent(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        init();
    }

    public CatLoadingComponent(Context context, AttrSet attrSet, int resId) {
        super(context, attrSet, resId);
        init();
    }

    private void init() {
        initPaint();
        try {
            text = getResourceManager().getElement(ResourceTable.String_cat_loading).getString();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NotExistException e) {
            e.printStackTrace();
        } catch (WrongTypeException e) {
            e.printStackTrace();
        } finally {
            if (text == null || "".equals(text))
                text = "LOADING...";
        }
        try {
            mCatHold = getPixMapHold(ResourceTable.Media_cat);
            catWidth = mCatHold.getPixelMap().getImageInfo().size.width;
            catHeight = mCatHold.getPixelMap().getImageInfo().size.height;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NotExistException e) {
            e.printStackTrace();
        }

        try {
            mMouseHold = getPixMapHold(ResourceTable.Media_mouse);
            mouseWidth = mMouseHold.getPixelMap().getImageInfo().size.width;
            mouseHeight = mMouseHold.getPixelMap().getImageInfo().size.height;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NotExistException e) {
            e.printStackTrace();
        }
        setBindStateChangedListener(new BindStateChangedListener() {
            @Override
            public void onComponentBoundToWindow(Component component) {
                if (autoStart) {
                    startAnimators();
                }
            }

            @Override
            public void onComponentUnboundFromWindow(Component component) {

            }
        });
        indicator = new Indicator<AnimatorValue>() {
            @Override
            public ArrayList<AnimatorValue> onCreateAnimators() {
                ArrayList<AnimatorValue> list = new ArrayList<>();
                AnimatorValue mouseAnimation = new AnimatorValue();
                mouseAnimation.setValueUpdateListener((animatorValue, v) -> {
                    mouseRorate = -360 * v % 360;
                    invalidate();
                });
                mouseAnimation.setLoopedCount(Animator.INFINITE);
                mouseAnimation.setCurveType(Animator.CurveType.LINEAR);
                mouseAnimation.setDuration(1000);
                list.add(mouseAnimation);

                AnimatorValue textAnimation = new AnimatorValue();
                textAnimation.setValueUpdateListener((animatorValue, v) -> {
                    progress = 100 * v;
                    invalidate();
                });
                textAnimation.setLoopedCount(Animator.INFINITE);
                textAnimation.setCurveType(Animator.CurveType.LINEAR);
                textAnimation.setDuration(2000);
                list.add(textAnimation);
                return list;
            }
        };
        addDrawTask(this);
    }


    @Override
    protected void stopAnimators() {

    }

    @Override
    protected void startAnimators() {
        if (text != null) {
            textLength = text.length();
            singleDuration = 100f / textLength;
        }
        if (indicator != null && !indicator.isRunning())
            indicator.start();
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        float width = Math.min(getWidth(), getHeight());
        //绘制最外层 嘴
        drawMouse(canvas);
        //绘制cat
        drawCat(canvas);
        //绘制眼球
        drawEyes(canvas);
        //绘制眼皮
        drawEyesRect(canvas);
        //绘制文本字样
        drawText(canvas);
    }

    private void drawMouse(Canvas canvas) {

        canvas.save();
        canvas.rotate(mouseRorate, getWidth() / 2f, getHeight() / 2f);
        //绘制嘴
        float mouseLeft = getWidth() / 2f - mouseWidth / 2f;
        float mouseTop = getHeight() / 2f - mouseHeight / 2f;
        canvas.drawPixelMapHolder(mMouseHold, mouseLeft, mouseTop, mPaint);
        canvas.restore();
    }

    //绘制眼镜
    public void drawEyes(Canvas canvas) {
        //绘制左边眼睛
        canvas.save();
        float left = getWidth() / 2f - 3 - 35;
        float top = getHeight() / 2f + 10 - 35;
        //设置一个38*38得区域为眼睛区域
        canvas.clipRect(new RectFloat(left, top, left + 38, top + 38));
        canvas.rotate(mouseRorate, left + 19, getHeight() / 2f - 5);
        //绘制眼球
        canvas.drawCircle(left + 10, getHeight() / 2f - 5, 4, mEyesPaint);
        canvas.restore();

        //绘制左边眼睛
        canvas.save();
        float r_left = getWidth() / 2f + 1;
        float r_top = getHeight() / 2f + 10 - 35;
        canvas.clipRect(new RectFloat(r_left, r_top, r_left + 38, r_top + 38));
        canvas.rotate(mouseRorate, r_left + 19, getHeight() / 2f - 5);
        canvas.drawCircle(r_left + 10, getHeight() / 2f - 5, 4, mEyesPaint);
        canvas.restore();

    }

    //绘制眼皮
    private void drawEyesRect(Canvas canvas) {
        float left = getWidth() / 2f - 3 - 35;
        float top = getWidth() / 2f + 10 - 35;
        float maxHeight = 38;
        float height = 0;
        //根据角度设置眼皮得覆盖区域
        if (Math.abs(mouseRorate) >= 0 && Math.abs(mouseRorate) <= 180) {
            //0-180度 眼球在下方 只显示一半眼睛
            height = maxHeight / 2f;
        } else {
            //180-360 眼球在上方 根据眼球位置设置眼皮覆盖区域
            height = (float) (maxHeight / 2f - maxHeight / 2f * Math.abs(Math.sin(Math.toRadians(mouseRorate))));
        }
        canvas.drawRect(left, top, left + 80, top + height, mEyesRectPaint);
    }

    private void drawText(Canvas canvas) {
        boolean isAnimationRunning = false;
        if (indicator != null) {
            isAnimationRunning = indicator.isRunning();
        }
        float textLeft = getWidth() / 2f - mouseWidth / 2f;

        float textRight = getHeight() - 100;
        if (isAnimationRunning) {
            textPaint.setAlpha(255);
            int lastOne = (int) (progress / singleDuration);
            if (progress / singleDuration >= 1) {
                canvas.drawText(textPaint,
                        text.substring(0, lastOne), textLeft, textRight
                );
            }
            textPaint.setAlpha((255 * (progress % singleDuration / singleDuration)));
            if (lastOne < textLength) {
                canvas.drawText(textPaint,
                        String.valueOf(text.charAt(lastOne)),
                        textLeft + textPaint.measureText(
                                text.subSequence(0, lastOne).toString()
                        ),
                        textRight
                );
            }
        } else {

        }
    }

    //绘制cat
    private void drawCat(Canvas canvas) {
        float left = getWidth() / 2f - catWidth / 2f;
        float top = getHeight() / 2f - catHeight / 2f;
        canvas.drawPixelMapHolder(mCatHold, left, top, mPaint);
    }

    private PixelMapHolder getPixMapHold(int id) throws IOException, NotExistException {
        Resource media = getContext().getResourceManager().getResource(id);
        ImageSource.SourceOptions Soptions = new ImageSource.SourceOptions();
        ImageSource imageSource = ImageSource.create(media, Soptions);
        ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
        PixelMap pix = imageSource.createPixelmap(decodingOptions);

        return new PixelMapHolder(pix);
    }

    private void initPaint() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(2);


        mEyesPaint = new Paint();
        mEyesPaint.setAntiAlias(true);
        mEyesPaint.setStrokeWidth(2);
        mEyesPaint.setColor(Color.BLACK);

        mEyesRectPaint = new Paint();
        mEyesRectPaint.setAntiAlias(true);
        mEyesRectPaint.setStrokeWidth(1);
        mEyesRectPaint.setColor(mEyesRectColor);
        mEyesRectPaint.setStyle(Paint.Style.FILL_STYLE);

        textPaint = new Paint();
        textPaint.setAntiAlias(true);
        textPaint.setColor(Color.WHITE);
        textPaint.setStyle(Paint.Style.FILL_STYLE);
        textPaint.setTextSize(36);


    }

}
